﻿using Mg.Domain;
using System;
using System.Collections.Generic;
using System.Collections.Concurrent;
using System.Linq;
using System.Reflection;

namespace Mg.Reflection
{
    public static class EntityPropertyInfoCollection
    {
        private static readonly ConcurrentDictionary<Type, PropertyInfo[]> _entityPropertyInfos = Init();

        static ConcurrentDictionary<Type, PropertyInfo[]> Init()
        {
            ConcurrentDictionary<Type, PropertyInfo[]> result = new ConcurrentDictionary<Type, PropertyInfo[]>();
            Type baseType = typeof(IEntity);
            IEnumerable<Type> entityTypes = GetAllType().Where(c => c.IsClass && !c.IsAbstract && baseType.IsAssignableFrom(c));
            foreach (Type item in entityTypes.Where(c => !result.ContainsKey(c)))
            {
                result[item] = item.GetProperties().Where(c => c.CanRead).ToArray();
            }
            return result;
        }

        public static PropertyInfo[] GetPropertyInfos(Type t)
        {
            return _entityPropertyInfos.ContainsKey(t) ? _entityPropertyInfos[t] : null;
        }

        public static List<Assembly> GetAllAssemblies()
        {
            return AppDomain.CurrentDomain.GetAssemblies().ToList();
        }

        public static List<Type> GetAllType()
        {
            var allTypes = new List<Type>();
            foreach (var assembly in GetAllAssemblies().Distinct())
            {
                try
                {
                    Type[] typeInAssembly;
                    try
                    {
                        typeInAssembly = assembly.GetTypes();
                    }
                    catch (ReflectionTypeLoadException ex)
                    {
                        typeInAssembly = ex.Types;
                    }
                    if (typeInAssembly == null || typeInAssembly.Count() < 1)
                        continue;
                    allTypes.AddRange(typeInAssembly.Where(c => c != null));
                }
                catch (Exception ex)
                {
                }
            }
            return allTypes;
        }

    }
}
